package main

import (
	"context"
	"fmt"
	"log"
	"os"
	"strconv"

	"github.com/shirou/gopsutil/v3/process"
)

func main() {
	// 检查命令行参数
	if len(os.Args) != 2 {
		fmt.Printf("用法: %s <PID>\n", os.Args[0])
		fmt.Println("示例: ", os.Args[0], "12345")
		os.Exit(1)
	}

	// 将输入的 PID 字符串转换为整数
	pid, err := strconv.Atoi(os.Args[1])
	if err != nil {
		log.Fatalf("无效的 PID: %s. 请输入一个数字。", os.Args[1])
	}

	fmt.Printf("========== 正在分析进程 (PID: %d) ==========\n", pid)

	// 使用 context 来允许未来可能的超时或取消操作
	ctx := context.Background()

	// 分析目标进程
	err = analyzeProcess(ctx, int32(pid), 0)
	if err != nil {
		log.Fatalf("分析进程 (PID: %d) 失败: %v", pid, err)
	}
}

// analyzeProcess 递归地分析一个进程及其子进程
// depth 参数用于缩进，以展示进程层级关系
func analyzeProcess(ctx context.Context, pid int32, depth int) error {
	// 根据 PID 创建一个 process.Process 对象
	p, err := process.NewProcess(pid)
	if err != nil {
		return fmt.Errorf("无法创建进程对象: %w", err)
	}

	// --- 获取进程基本信息 ---

	// 获取进程名称
	name, err := p.Name()
	if err != nil {
		name = "N/A"
	}

	// 获取命令行参数
	cmdline, err := p.CmdlineSlice()
	if err != nil {
		cmdline = []string{"N/A"}
	}

	// 获取当前工作目录
	cwd, err := p.Cwd()
	if err != nil {
		cwd = "N/A"
	}

	// --- 打印进程信息 ---

	// 根据深度生成缩进，使输出更具可读性
	indent := ""
	for i := 0; i < depth; i++ {
		indent += "  "
	}

	fmt.Printf("%s[PID: %d]\n", indent, pid)
	fmt.Printf("%s  名称: %s\n", indent, name)
	fmt.Printf("%s  工作目录: %s\n", indent, cwd)
	fmt.Printf("%s  命令行: %v\n", indent, cmdline)

	// --- 获取并递归分析子进程 ---

	childrenPids, err := p.Children()
	if err != nil {
		fmt.Printf("%s  警告: 无法获取子进程列表: %v\n", indent, err)
		return nil // 即使无法获取子进程，也不认为是致命错误
	}

	if len(childrenPids) > 0 {
		fmt.Printf("%s  子进程:\n", indent)
		for _, childPid := range childrenPids {
			// 递归分析每个子进程，深度加一
			if err := analyzeProcess(ctx, childPid.Pid, depth+1); err != nil {
				// 如果某个子进程分析失败（例如已退出），打印警告并继续
				fmt.Printf("%s    警告: 分析子进程 (PID: %d) 失败: %v\n", indent, childPid.Pid, err)
			}
		}
	}

	return nil
}
